use std::{collections::HashMap, fmt::format, sync::Arc};

use crate::{utils::get_context_key, AppError, AppResult, AppState};
use ane_cms::dao::{ArticleListVo, ArticleVo, Cms};
use axum::{
    extract::{MatchedPath, NestedPath, Path, Query, State},
    http::Uri,
    response::{IntoResponse, Response},
    Extension, Json, Router,
};
use axum::{handler::Handler, routing::get};
use common::page::{PageInfo, PageParams};
use sea_orm::{sea_query::Nullable, DbConn};
use serde::{Deserialize, Serialize};

/// CMS 公开的接口
pub fn get_route(prefix: &str) -> Router<AppState> {
    let f = move |p: &str| -> String { format!("{}{p}", prefix) };
    Router::new()
        .route(&f("/article"), get(list_article))
        .route(&f("/article/:id"), get(fetch_article))
        .route(&f("/category/"), get(list_category))
}

#[derive(Debug, Deserialize)]
struct Filter {
    key: Option<String>,
    catogory_id: Option<i32>,
    tag: Option<String>,
}

async fn list_article(
    Query(page_params): Query<PageParams>,
    Query(filter): Query<Filter>,
    State(state): State<AppState>,
) -> AppResult<impl IntoResponse> {
    Cms::list_article::<ArticleListVo>(
        state.db(),
        page_params.zero_page(),
        page_params.page_size(),
        filter.catogory_id,
        filter.key,
    )
    .await
    .map(|data| {
        if let Some((data, total, _)) = data {
            PageInfo::new(data, &page_params, total)
        } else {
            PageInfo::new(vec![], &page_params, 0)
        }
    })
    .map(Json)
    .map_err(Into::into)
}

async fn fetch_article(
    Path(id): Path<i32>,
    State(state): State<AppState>,
) -> AppResult<impl IntoResponse> {
    Cms::fetch_article::<ArticleVo>(state.db(), id)
        .await
        .map(Json)
        .map_err(Into::into)
}

async fn list_category(State(state): State<AppState>) -> AppResult<impl IntoResponse> {
    Cms::fetch_category(state.db(), Some(1))
        .await
        .map(Json)
        .map_err(Into::into)
}
